﻿using Behaving;
using Behaving.Composites;
using FluentAssertions;
using NUnit.Framework;

namespace Behaving.Tests.CompositeTests
{
    [TestFixture]
    public class ConditionalTests
    {     
        [Test]
        public void When_can_run_with_no_else_is_run()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counter;
            behaviourTree.Root = new Conditional(() => true, counter = new ExecutionCounter(RunningState.Running));
            behaviourTree.Tick().Should().Be(RunningState.Running);
            Assertions.AssertWasStartedAndExecuted(counter);
        }

        [Test]
        public void When_cant_run_with_no_else_is_run()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counter;
            behaviourTree.Root = new Conditional(() => false, counter = new ExecutionCounter(RunningState.Running));
            behaviourTree.Tick().Should().Be(RunningState.Failure);
            Assertions.AssertWasNotCalled(counter);
        }

        [Test]
        public void When_a_cant_run_with_running_child_with_no_else_is_run()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counter;
            behaviourTree.Root = new Conditional(() => false, counter = new ExecutionCounter(RunningState.Running));
            behaviourTree.SetWasRunningPreviousTick(behaviourTree.Root);
            behaviourTree.SetWasRunningPreviousTick(counter);

            behaviourTree.Tick().Should().Be(RunningState.Failure);
            Assertions.AssertWasStopped(counter);
        }

        [Test]
        public void When_a_can_run_with_else_is_run()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counterCan;
            ExecutionCounter counterElse;
            behaviourTree.Root = new Conditional(() => true, counterCan = new ExecutionCounter(RunningState.Running).SetName("Can"), counterElse = new ExecutionCounter().SetName("Else"));
            behaviourTree.Tick().Should().Be(RunningState.Running);
            Assertions.AssertWasStartedAndExecuted(counterCan);
            Assertions.AssertWasNotCalled(counterElse);
        }

        [Test]
        public void When_a_cant_run_false_with_else_is_run()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counterCan;
            ExecutionCounter counterElse;
            behaviourTree.Root = new Conditional(() => false, counterCan = new ExecutionCounter(RunningState.Running).SetName("Can"), counterElse = new ExecutionCounter(RunningState.Running).SetName("Else"));
            behaviourTree.Tick().Should().Be(RunningState.Running);
            Assertions.AssertWasStartedAndExecuted(counterElse);
            Assertions.AssertWasNotCalled(counterCan);
        }

        [Test]
        public void When_a_conditional_switches_running_from_can_to_cant()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counterCan;
            ExecutionCounter counterElse;
            behaviourTree.Root = new Conditional(() => false, counterCan = new ExecutionCounter(RunningState.Running).SetName("Can"), counterElse = new ExecutionCounter(RunningState.Running).SetName("Else"));

            behaviourTree.SetWasRunningPreviousTick(behaviourTree.Root);
            behaviourTree.SetWasRunningPreviousTick(counterCan);
            behaviourTree.Tick().Should().Be(RunningState.Running);
            Assertions.AssertWasStartedAndExecuted(counterElse);
            Assertions.AssertWasStopped(counterCan);
        }

        [Test]
        public void When_a_conditional_switches_running_from_else_to_can()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            ExecutionCounter counterCan;
            ExecutionCounter counterElse;
            behaviourTree.Root = new Conditional(() => true, counterCan = new ExecutionCounter(RunningState.Running).SetName("Else"), counterElse = new ExecutionCounter(RunningState.Running).SetName("Else"));
            behaviourTree.SetWasRunningPreviousTick(behaviourTree.Root);
            behaviourTree.SetWasRunningPreviousTick(counterElse);
            behaviourTree.Tick().Should().Be(RunningState.Running);
            Assertions.AssertWasStartedAndExecuted(counterCan);
            Assertions.AssertWasStopped(counterElse);
        }
    }
}